package com.zxy.ziems.server.oauth.service;

import com.alibaba.fastjson.JSONObject;
import com.zxy.btp.common.dto.ReturnUserInfo;
import com.zxy.btp.common.util.JsonUtils;
import com.zxy.btp.security.bean.TokenEntity;
import com.zxy.btp.security.service.LoginService;
import com.zxy.btp.security.service.TokenService;
import com.zxy.ziems.server.foms.dto.TenantUser;
import com.zxy.ziems.server.foms.dto.UserInfo;
import com.zxy.ziems.server.foms.service.FomsRpcService;
import com.zxy.ziems.server.oauth.vo.BoeplatOauthBean;
import com.zxy.ziems.server.oauth.vo.OauthToekenVo;
import com.zxy.ziems.server.service.UserService;
import com.zxy.ziems.server.utils.BusinessExceptionUtil;
import com.zxy.ziems.server.utils.OkHttpUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class BoeplatAauthService {

    private Logger logger = LoggerFactory.getLogger(BoeplatAauthService.class);

    @Value("${zifoms-server.config.clientSecret}")
    private String clientSecret;
    @Value("${zifoms-server.config.homePage}")
    private String homePage;
    @Value("${zifoms-server.config.oauthToken}")
    private String oauthUrl;

    @Autowired
    private FomsRpcService fomsRpcService;
    @Autowired
    private UserService userService;
    @Autowired
    private LoginService loginService;
    @Autowired
    private com.zxy.btp.security.service.UserService loginUserService;
    @Autowired
    private TokenService tokenService;

    public OauthToekenVo oauthToken(String clientId, String tenantId, String oauthCode,
                                    String appNum, HttpServletResponse response, HttpServletRequest httpRequest) throws Exception {
        if (StringUtils.isEmpty(clientId) || StringUtils.isEmpty(oauthCode)) {
            throw BusinessExceptionUtil.exception("缺少必要参数");
        }
        Map<String, String> header = new HashMap<>();
        header.put("Authorization", genBasicSecret(clientId, clientSecret));
        Map<String, String> requestParam = new HashMap<>();
        requestParam.put("clientId", clientId);
        requestParam.put("grant_type", "authorization_code");
        requestParam.put("scope", "all");
        requestParam.put("client_secret", clientSecret);
        requestParam.put("code", oauthCode);
        requestParam.put("tenantId", Optional.ofNullable(tenantId).orElse(""));
        Map<String, String> msgMap = new HashMap<>();
        String[] redirectUris = homePage.split(",");
        for (String redirectUri : redirectUris) {
            requestParam.put("redirect_uri", redirectUri.trim());
            String responseStr = OkHttpUtil.postForm(oauthUrl, requestParam, header);
            Map<String, Object> responseMap = JSONObject.parseObject(responseStr, Map.class);
            String code = MapUtils.getString(responseMap, "code");
            String message = MapUtils.getString(responseMap, "message");
            logger.info("授权码换取token，tenantId->{}，code->{}", tenantId, oauthCode);
            msgMap.put(code, Optional.ofNullable(message).orElse(JsonUtils.toJSONString(responseMap)));
        }

        if (!msgMap.keySet().contains("0")) {
            for (Map.Entry<String, String> msgEnty : msgMap.entrySet()) {
                if (!"0".equals(msgEnty.getKey())) {
                    throw BusinessExceptionUtil.exception(Integer.parseInt(msgEnty.getKey()), msgEnty.getValue());
                }
            }
        }
        //将数据权限写入token
        Map<String, Object> claims = new HashMap<>();
        BoeplatOauthBean oauthBean = JsonUtils.parseObject(msgMap.get("0"), BoeplatOauthBean.class);

        //20230228临时功能：外网只允许白名单人员登录
        //20230705关闭白名单功能
//        String app = httpRequest.getHeader("app");
//        if (!StringUtils.isEmpty(app)) {
//            if (!checkInWhiteList(oauthBean.getUserId(), oauthBean.getTenantId(), Integer.parseInt(app))) {
//                throw new BaseException("无外网访问权限");
//            }
//        }

        //更换 数据从厂务获取
        TenantUser tenantUser = fomsRpcService.loadByUserId(oauthBean.getUserId(), oauthBean.getTenantId());


        //用户为超级用户时，自动绑定全部页面资源权限
        userService.initResources(tenantUser);

        Integer dataPermission = 3; // 全部
        List<String> deptIds = Arrays.asList(tenantUser.getDeptId());
        claims.put("deptId", tenantUser.getDeptId());
        claims.put("dataPermission", dataPermission);
        claims.put("userId", oauthBean.getUserId());
        claims.put("tenantId", oauthBean.getTenantId());
        claims.put("userName", tenantUser.getUserName());
        claims.put("tenantName", tenantUser.getTenantName());
        claims.put("firmCode", tenantUser.getFirmCode());
        claims.put("deptName", tenantUser.getDeptName());
        claims.put("deptIds", deptIds);
        claims.put("appNum", appNum);

        // 调用登录获取登录token
        UserInfo userInfo = fomsRpcService.getUserInfo(oauthBean.getUserId());
        ReturnUserInfo userDetail = loginUserService.getUserDetail(userInfo.getPhone());
        userDetail.setAuthentication(true);

        TokenEntity tokenEntity = this.tokenService.createToken(userDetail, null);
        String accessToken = tokenEntity.getAccessToken();
        OauthToekenVo toekenVo = new OauthToekenVo();
        toekenVo.setAccessToken(accessToken);
        toekenVo.setUserId(oauthBean.getUserId());
        toekenVo.setTenantId(oauthBean.getTenantId());
        toekenVo.setDeptId(tenantUser.getDeptId());
        toekenVo.setTokenKey("ziems-ut");
        toekenVo.setExpiresIn(oauthBean.getExpiresIn());
        toekenVo.setUt(accessToken);
        logger.info("token获取成功，{}", accessToken);
//        this.addLoginLog(oauthBean.getTenantId(), tenantUser.getTenantName(), tenantUser.getDeptId(), oauthBean.getUserId(), tenantUser.getUserName());
        return toekenVo;
    }

    public String genBasicSecret(String clientId, String clientSecret) {
        String clientInfo = clientId + ":" + clientSecret;
        String baseStr = Base64.getEncoder().encodeToString(clientInfo.getBytes());
        String stringBuilder = "Basic " + baseStr;
        return stringBuilder;
    }
}
